package com.fruit.auth.service.impl;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.fruit.auth.dao.PrivilegeDao;
import com.fruit.auth.model.Privilege;
import com.fruit.auth.service.PrivilegeService;

@Service("privilegeService")
public class PrivilegeServiceImpl implements PrivilegeService
{
	@Resource(name="privilegeDao")
	private PrivilegeDao privilegeDao;
	
	public Object[] savePrivilege(Privilege privilege)
	{
		String hql;
		//如果权限的url为空则可直接插入，例如系统顶级菜单，如果url不为空，为了保证url的唯一性必须先查询数据库看是否已经存在该url
		if(privilege.getUrl()!=null)
		{
			hql="select count(*) from Privilege where url=?";
			Long count=(Long) privilegeDao.findUniqueResultByHql(hql, privilege.getUrl());
			if(count!=0)
				return null;
		}
		hql="select max(p.privilegePos) ,max(p.privilegeCode) from Privilege p where p.privilegePos=(select max(privilegePos) from Privilege)";
		Object[] privilegeArr=(Object[]) privilegeDao.findUniqueResultByHql(hql);
		Integer pos=0;
		Long code=1L;
		if(privilegeArr!=null&&privilegeArr[0]!=null)
		{
			int maxPos=(int) privilegeArr[0];
			long maxCode=(long) privilegeArr[1];
			if(maxCode>=(1L<<60))
			{
				pos=maxPos+1;
				code=1L;
			}
			else
			{
				pos=maxPos;
				code=maxCode<<1;
			}
		}
		privilege.setPrivilegePos(pos);
		privilege.setPrivilegeCode(code);
		privilegeDao.saveEntity(privilege);
		return new Object[]{pos,code};
	}

	public List<Privilege> findAllPrivileges()
	{
		//TODO 二级缓存
		return privilegeDao.findAllEntity();
	}
	
	public List<Privilege> findTreePrivileges()
	{
		//TODO 二级缓
		List<Privilege> allPrivileges=findAllPrivileges();
		List<Privilege> rootPrivileges=filterRootPrivileges(allPrivileges);
		for(Privilege p:rootPrivileges)
			loopPrivilege(null, p,allPrivileges);
		return rootPrivileges;	
	}
	
	public List<Privilege> findTreePrivilegesForRole(Serializable roleId)
	{
		//TODO 二级缓，roleId参数缓存
		List<Privilege> privileges=findPrivilegesForRole(roleId);
		List<Privilege> rootPrivileges=filterRootPrivileges(privileges);
		for(Privilege rootPrivilege:rootPrivileges)
			loopPrivilege(null, rootPrivilege,privileges);
		return rootPrivileges;	
	}
	
	public List<Privilege> findTreePrivilegesForUser(Serializable userId)
	{
		List<Privilege> privileges=findPrivilegesForUser(userId);
		List<Privilege> rootPrivileges=filterRootPrivileges(privileges);
		for(Privilege rootPrivilege:rootPrivileges)
			loopPrivilege(null, rootPrivilege,privileges);
		return rootPrivileges;	
	}
	
	/**
	 * 
	 * @param privilege 指定查找谁的子级权限
	 * @param privilegesContainer 权限容器，指定从哪里查找，该参数的作用主要是加快查找速度
	 * @return
	 */
	private List<Privilege> findChildrenPrivileges(Privilege privilege,List<Privilege> privilegesContainer)
	{
		List<Privilege> childPrivileges=new ArrayList<Privilege>();
		if(!CollectionUtils.isEmpty(privilegesContainer))
		{
			for(Privilege p:privilegesContainer)
			{
				
				if(p.getParent()==privilege)
					childPrivileges.add(p);
			}
		}
		return childPrivileges;
	}
	
	private List<Privilege> filterRootPrivileges(List<Privilege> privilegeContainer)
	{
		List<Privilege> rootPrivileges=new ArrayList<Privilege>();
		if(!CollectionUtils.isEmpty(privilegeContainer))
		{
			for(Privilege p:privilegeContainer)
			{
				if(p.getParent()==null)
					rootPrivileges.add(p);
			}
		}
		return rootPrivileges;
	}
	
	private void loopPrivilege(Privilege parent,Privilege privilege,List<Privilege> privilegeContainer)
	{
		if(privilege!=null)
		{
			List<Privilege> childPrivileges=findChildrenPrivileges(privilege,privilegeContainer);
			if(CollectionUtils.isEmpty(childPrivileges))
				privilege.setChildren(null);
			else
			{
				privilege.setChildren(childPrivileges);
				for(Privilege child:childPrivileges)
				{
					child.setParent(null);
					loopPrivilege(privilege, child,privilegeContainer);
				}
			}
		}
	}
	
	
//	@Override
//	public List<Privilege> findTreePrivileges()
//	{
//		String hql="from Privilege p where p.parent=null";
//		List<Privilege> privileges=privilegeDao.findEntityByHql(hql);
//		for(Privilege p:privileges)
//			getChildNodes(p);
//		return privileges;
//	}
	
//	private void getChildNodes(Privilege privilege)
//	{
//		if(privilege!=null)
//		{
//			for(Privilege p:privilege.getChildren())
//			{
//				//如果没有这行会导致StackOverFlowException 循环引用
//				p.setParent(null);
//				getChildNodes(p);
//			}
//		}
//	}
	
	public List<Privilege> findPrivilegesForUser(Serializable userId)
	{
		return privilegeDao.findPrivilegesForUser(userId);
	}
	
	public List<Privilege> findPrivilegesForRole(Serializable roleId)
	{
		return privilegeDao.findPrivilegesForRole(roleId);
	}

	@Override
	public Privilege loadPrivilege(Serializable privilegeId)
	{
		return privilegeDao.loadEntity(privilegeId);
	}

	@Override
	public void deletePrivilege(Serializable privilegeId)
	{
		privilegeDao.batchEntityByHql("delete from Privilege where id=?", privilegeId);
		
	}

	@Override
	public void updatePrivilege(Privilege privilege)
	{
		privilegeDao.updateEntity(privilege);
	}
	
	@Override
	public Privilege findPrivilege(Serializable privilegeId)
	{
		return privilegeDao.getEntity(privilegeId);
	}
	
	public int getMaxPrivilegePos()
	{
		return (int) privilegeDao.findUniqueResultByHql("select max(privilegePos) from Privilege");
	}
}
